package org.example2;

/**
 * 手写JDK动态代理核心原理
 *
 * 自定义的classloader,自定义的InvocationHandler
 *      不仅知其然, 还得知其所以然.既然JDK动态代理的功能如此强大, 那么它是如何实现的呢？现在来探究一下原理, 
 * 并模仿JDK动态代理手写一个属于自己的动态代理.
 * 我们都知道JDK动态代理采用字节重组, 重新生成对象来替代原始对象, 以达到动态代理的目的.JDK动态代理生成对象的步骤如下.
 * （1）获取被代理对象的引用,并且获取它的所有接口, 反射获取.
 * （2）JDK动态代理类重新生成一个新的类, 同时新的类要实现被代理类实现的所有接口.
 * （3）动态生成Java源代码代码, 新加的业务逻辑方法由一定的逻辑代码调用（在代码中体现）.
 * （4）编译新生成的Java代码.class文件.
 * （5）重新加载到JVM中运行.
 * 以上过程就叫作字节码重组. JDK中有一个规范, 在ClassPath下只要是$开头的.class文件, 一般都是自动生成的.那么有没有办法看到代替
 * 后的对象的“真容”呢？做一个这样的测试, 将内存中的对象字节码通过文件流输出到一个新的.class文件, 然后使用反编译工具查看源码.
 * 作者: Tom弹架构
 * 链接: https://www.imooc.com/article/321427
 * 来源: 慕课网
 * 本文原创发布于慕课网 , 转载请注明出处, 谢谢合作
 *
 * https://baijiahao.baidu.com/s?id=1714701162927866378&wfr=spider&for=pc
 *
 *  程序生成源码,编译并调用
 *
 */
public class AppCustomerJdkProxyImplements {
    public static void main(String[] args) {
        ZhangSan originZhangSan = new ZhangSan();
        CustomerProxyFactory proxyFactory = new CustomerProxyFactory(originZhangSan);
        System.out.println("originZhangSan的hashCode是:"+System.identityHashCode(originZhangSan));
        IPerson proxyZhangSan = proxyFactory.getInstance(originZhangSan);
        System.out.println("proxyZhangSan的hashCode是:"+System.identityHashCode(proxyZhangSan));

        System.out.println();
        proxyZhangSan.findLove();
        System.out.println();
        String selfInfo = proxyZhangSan.introduceMyself("张三", 24);
        System.out.println("selfInfo="+selfInfo);
    }

}